/*
** realloc.c for malloc in /home/morel_t//Rendu/systemUnix/malloc
**
** Made by thomas morel
** Login   <morel_t@epitech.net>
**
** Started on  Thu Feb  2 15:30:41 2012 thomas morel
** Last update Fri Feb  3 12:12:33 2012 florian jousseau
*/

#include <pthread.h>
#include <string.h>
#include "alloc.h"

static void	*size_null(void *ptr)
{
  free(ptr);
  return (NULL);
}

static void	enough_space(t_alloc block, size_t size)
{
  if ((block->size - size) >= (BLOCK_SIZE))
    split_block(block, size);
}

static void	enough_space_with_next(t_alloc block, size_t size)
{
  merge_block(block);
  split_block(block, size);
}

static void	*not_enough_space(void *ptr, size_t size)
{
  void		*new_ptr;

  new_ptr = malloc(size);
  if (new_ptr == NULL)
    return (NULL);
  memcpy(new_ptr, ptr, size);
  free(ptr);
  return (new_ptr);
}

void	*realloc(void *ptr, size_t size)
{
  t_alloc	block;

  if (ptr == NULL)
    return (malloc(size));
  if (size == 0)
    return (size_null(ptr));
  if (inside_heap(ptr))
    {
      size = align4(size);
      block = get_mdata(ptr);
      if (block->size >= size)
	enough_space(block, size);
      else
      	{
	  if (block->next && block->next->free
	      && (block->size + (BLOCK_SIZE) + block->next->size) >= size)
	    enough_space_with_next(block, size);
	  else
	    return (not_enough_space(ptr, size));
	}
      return (ptr);
    }
  return (NULL);
}
